Timeline Grouping


Use the Timeline Grouping to group the data in a timeline view to display a list of events in chronological order. The timeline view is generally used if there is only one level of grouping and the data type of the grouped column is object data.

Use the following steps to implement the Timeline Grouping.

Sample Code

  1. Add the following references after the Dataview reference.
    <script src="[Your Script Path]/gc.spread.views.timelinegrouping.10.1.1.min.js"></script>
    <link rel="stylesheet" href="[Your Stylesheet Path]/gc.spread.views.timelinegrouping.10.1.1.css" type="text/css">
    </script>
  2. Add a div tag within the body tag to include the DOM element as the container in the page.
    <div style="height: 100%; position: relative">
            <div class="button-container " id="timelineCommandPanel">
                <div class="timelineLeftBtns">
                    <div class="btn-group" role="group">
                        <button id="headerBtn" style="width:120px" type="button" class="btn btn-default" onclick="changeGroupHeader()">showHeader
                    </button>
                        <button id="headerLocationBtn" style="width:120px" type="button" class="btn btn-default" onclick="changeHeaderLocation()">Location: top
                    </button>
                    </div>
                </div>
                <div class="timelineRightBtns">
                    <div class="btn-group" role="group">Display:</div>
                    <div class="btn-group" role="group">
                        <div id="left-btn" class="btn btn-default" onclick="changeToLeft()">Left</div>
                        <div id="middle-btn" class="btn btn-default active" onclick="changeToMiddle()">Middle</div>
                        <div id="right-btn" class="btn btn-default" onclick="changeToRight()">Right</div>
                    </div>
                </div>
            </div>
            <div id="gridContainer" style="height:420px;">
                <div id="grid1" style="height:100%;position: relative"></div>
            </div>
    </div>
  3. Add a variable definition followed by the column definition.

    var timeFormatter = 'HH:mmtt';
            var showGroupHeader = false;
            var axisLocation = 'middle';
            var headerLocation = 'top';
            var imageNames = ['ds', 'gw', 'bw', 'hh', 'ac'];
            var index = 0;
    
            var presenter = '<img class="employee-photo" src={{=it.photo}} />';
            var columns = [{
                id: 'topic',
                dataField: 'topic'
            }, {
                id: 'start',
                dataField: 'start',
                format: 'MMMM dd, HH:mmtt'
            }, {
                id: 'end',
                dataField: 'end',
                format: timeFormatter
            }, {
                id: 'speaker',
                dataField: 'speaker'
            }, {
                id: 'content',
                dataField: 'content'
            }, {
                id: 'photo',
                dataField: 'photo',
                presenter: presenter
            }];
            var groupDetailEventTemplate = '<div style="margin:5px;">' +
                '<div style="font-size:14px;font-weight: bold;">{{=it.topic}}</div>' +
                '<blockquote style="padding-left: 15px;display: block;font-size:13px;font-family: "Helvetic Neue, Helvetica, Arial">{{=it.content}}</blockquote>' +
                '<span style="margin-right: auto" >{{=it.start}}</span>' +
                '</div>';
            var groupSummaryEventTemplate = '<div style="margin:5px;height:60px;">' +
                '<div style="position:absolute;left:0px;width:50px;" data-column="photo"></div>' +
                '<div style="position:absolute;left:50px;">' +
                '<div>{{=it.topic}}</div>' +
                '<div>{{=it.start}}' +
                '</div>'
            '</div>'
    
            var groupHeaderMiddleTemplate = '<div>' +
                '<div style="top:12px;text-align: center;">' +
                '<div>' +
                '<div style="font-size:12px;display: inline-block;background: #ffffff;color:#131313;padding:5px;border-top:3px solid red; border-left: 1px solid rgba(208, 209, 206, 0.99);border-right: 1px solid rgba(208, 209, 206, 0.99);border-bottom: 1px solid rgba(208, 209, 206, 0.99)">' +
                '<div>{{=it.name}}</div>' +
                '</div>' +
                '</div>' +
                '</div></div>';
    
            var groupHeaderLeftTemplate = '<div style="position: relative;">' +
                '<div style="padding-left:20px;font-size:20px;"><span style="color:#131313;">{{=it.name}}</span></div>' +
                '</div>';
    
            var groupHeaderRightTemplate = '<div style="position: relative;">' +
                '<div style="padding-right:20px;font-size:20px;text-align: right;"><span style="color:#131313;">{{=it.name}}</span></div>' +
                '</div>';
    
            var gHLeftTemplate = '<div style="margin-left:50px">' +
                '<div style="width:26px;height:26px;border-radius:50%;background-color: #AB47BC;"></div>' +
                '<span style="margin-left: -5px;background-color: white">{{=it.name}}<span>' +
                '</div>';
    
            var gHMiddleTemplate = '<div style="text-align: center">' +
                '<div style="display: inline-block">' +
                '<div style="margin-left:11px; width:26px;height:26px;border-radius:50%;background-color: #AB47BC;"></div>' +
                '<span style="background-color: white">{{=it.name}}<span>' +
                '</div>' +
                '</div>';
    
            var gHRightTemplate = '<div style="float:right;margin-right:33px">' +
                '<div style="width:26px;height:26px;border-radius:50%;background-color: #AB47BC;"></div>' +
                '<span style="margin-left: -5px;background-color: white">{{=it.name}}<span>' +
            '</div>';
  4. Initialize the code by calling the Grid ID from the DIV tag.
    var items = [];
            $.each(data, function(key, val) {
                for (var prop in val) {
                    if (prop === 'start' || prop === 'end') {
                        val[prop] = new Date(val[prop]);
                    }
                }
                val.photo = './images/' + getImage();
            });
            var excelFormatter = new GC.Spread.Formatter.GeneralFormatter('mmmm dd');
            //triangle
            var TimelineGrouping = new GC.Spread.Views.Plugins.TimelineGrouping({});
            var dataView = new GC.Spread.Views.DataView(document.getElementById('grid1'), data, columns, new GC.Spread.Views.Plugins.GridLayout({
                grouping: {
                    field: 'start',
                    converter: function(field) {
                        return excelFormatter.format(field);
                    }
                },
                autoRowHeight: true,
                rowTemplate: groupDetailEventTemplate,
                groupStrategy: TimelineGrouping
        }));
  5. Add functions to update the timeline.

    function getImage() {
                var imageName;
                imageName = imageNames[index % 5];
                index++;
                return imageName + '.jpg';
            }
    
            function changeGroupHeader() {
                showGroupHeader = !showGroupHeader;
                update();
            }
    
            function changeHeaderLocation() {
                if (headerLocation === 'top') {
                    headerLocation = 'onAxis';
                } else {
                    headerLocation = 'top'
                }
                update();
            }
    
            function changeToLeft() {
                $('#left-btn').addClass('active');
                $('#middle-btn').removeClass('active');
                $('#right-btn').removeClass('active');
                axisLocation = 'left';
                update();
            }
    
            function changeToMiddle() {
                $('#middle-btn').addClass('active');
                $('#left-btn').removeClass('active');
                $('#right-btn').removeClass('active');
                axisLocation = 'middle';
                update();
                dataView.invalidate();
            }
    
            function changeToRight() {
                $('#right-btn').addClass('active');
                $('#left-btn').removeClass('active');
                $('#middle-btn').removeClass('active');
                axisLocation = 'right';
                update();
                dataView.invalidate();
            }
    
            function update() {
                var template;
                if (headerLocation === 'top') {
                    template = axisLocation === 'left' ? groupHeaderLeftTemplate : (axisLocation === 'right' ? groupHeaderRightTemplate : groupHeaderMiddleTemplate);
                } else {
                    template = axisLocation === 'left' ? gHLeftTemplate : (axisLocation === 'right' ? gHRightTemplate : gHMiddleTemplate);
                }
                var options = dataView.options;
                TimelineGrouping.options.axisLocation = axisLocation;
                var btn = document.getElementById('headerBtn');
                var headerLocationBtn = document.getElementById('headerLocationBtn');
                headerLocationBtn.textContent = 'Location: ' + headerLocation;
                TimelineGrouping.options.groupHeaderLocation = headerLocation;
                var grouping = dataView.data.groupDescriptors[0];
                if (showGroupHeader) {
                    grouping.header.visible = true;
                    grouping.header.template = template;
                    if (headerLocation === 'top') {
                        TimelineGrouping.options.gutter = 13;
                        grouping.header.height = 35;
                    } else {
                        TimelineGrouping.options.gutter = 120;
                        grouping.header.height = 60;
                    }
    
                    options.rowTemplate = groupSummaryEventTemplate;
                    btn.textContent = 'hideHeader';
                } else {
                    grouping.header.template = null;
                    grouping.header.visible = false;
                    options.rowTemplate = groupDetailEventTemplate;
                    btn.textContent = 'showHeader';
                    TimelineGrouping.options.gutter = 13;
                }
    
                dataView.invalidate();
        }